// Geometric Tools, Inc.
// http://www.geometrictools.com
// Copyright (c) 1998-2006.  All Rights Reserved
//
// The Wild Magic Library (WM3) source code is supplied under the terms of
// the license agreement
//     http://www.geometrictools.com/License/WildMagic3License.pdf
// and may not be copied or disclosed except in accordance with the terms
// of that agreement.

#ifndef WM3MASSSPRINGCURVE_H
#define WM3MASSSPRINGCURVE_H

#include "Wm3FoundationLIB.h"
#include "Wm3ParticleSystem.h"

namespace Wm3
{

template <class Real, class TVector>
class WM3_ITEM MassSpringCurve : public ParticleSystem<Real,TVector>
{
public:
    // Construction and destruction.  This class represents a set of N-1
    // springs connecting N masses that lie on a curve.  Spring i connects
    // masses i-1 and i for 1 <= i <= N-1.
    MassSpringCurve (int iNumParticles, Real fStep);
    virtual ~MassSpringCurve ();

    int GetNumSprings () const;
    Real& Constant (int i);  // spring constant
    Real& Length (int i);  // spring resting length

    // Callback for acceleration (ODE solver uses x" = F/m) applied to
    // particle i.  The positions and velocities are not necessarily
    // m_akPosition and m_akVelocity since the ODE solver evaluates the
    // impulse function at intermediate positions.
    virtual TVector Acceleration (int i, Real fTime,
        const TVector* akPosition, const TVector* akVelocity);

    // The default external force is zero.  Derive a class from this one to
    // provide nonzero external forces such as gravity, wind, friction,
    // and so on.  This function is called by Acceleration(...) to append the
    // acceleration F/m generated by the external force F.
    virtual TVector ExternalAcceleration (int i, Real fTime,
        const TVector* akPosition, const TVector* akVelocity);

protected:
    using ParticleSystem<Real,TVector>::m_iNumParticles;
    using ParticleSystem<Real,TVector>::m_afInvMass;

    int m_iNumSprings;
    Real* m_afConstant;
    Real* m_afLength;
};

typedef MassSpringCurve<float,Vector2f> MassSpringCurve2f;
typedef MassSpringCurve<double,Vector2d> MassSpringCurve2d;
typedef MassSpringCurve<float,Vector3f> MassSpringCurve3f;
typedef MassSpringCurve<double,Vector3d> MassSpringCurve3d;

}

#endif

